
<!DOCTYPE html
  PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
   
      <title>7.3.&nbsp;个案研究：罗马字母</title>
      <link rel="stylesheet" href="../diveintopython.css" type="text/css">
      <link rev="made" href="mailto:f8dy@diveintopython.org">
      <meta name="generator" content="DocBook XSL Stylesheets V1.52.2">
      <meta name="keywords" content="Python, Dive Into Python, tutorial, object-oriented, programming, documentation, book, free">
      <meta name="description" content="Python from novice to pro">
      <link rel="home" href="../toc/index.html" title="Dive Into Python">
      <link rel="up" href="index.html" title="第&nbsp;7&nbsp;章&nbsp;正则表达式">
      <link rel="previous" href="street_addresses.html" title="7.2.&nbsp;个案研究：街道地址">
      <link rel="next" href="n_m_syntax.html" title="7.4.&nbsp;使用 {n,m} 语法">
   </head>
   <body>
      <table id="Header" width="100%" border="0" cellpadding="0" cellspacing="0" summary="">
         <tr>
            <td id="breadcrumb" colspan="5" align="left" valign="top">导航：<a href="../index.html">起始页</a>&nbsp;&gt;&nbsp;<a href="../toc/index.html">Dive Into Python</a>&nbsp;&gt;&nbsp;<a href="index.html">正则表达式</a>&nbsp;&gt;&nbsp;<span class="thispage">个案研究：罗马字母</span></td>
            <td id="navigation" align="right" valign="top">&nbsp;&nbsp;&nbsp;<a href="street_addresses.html" title="上一页: “个案研究：街道地址”">&lt;&lt;</a>&nbsp;&nbsp;&nbsp;<a href="n_m_syntax.html" title="下一页: “使用 {n,m} 语法”">&gt;&gt;</a></td>
         </tr>
         <tr>
            <td colspan="3" id="logocontainer">
               <h1 id="logo"><a href="../index.html" accesskey="1">深入 Python :Dive Into Python 中文版</a></h1>
               <p id="tagline">Python 从新手到专家 [Dip_5.4b_CPyUG_Release]</p>
            </td>
            <td colspan="3" align="right">
               <form id="search" method="GET" action="http://www.google.com/custom">
                  <p><label for="q" accesskey="4">Find:&nbsp;</label><input type="text" id="q" name="q" size="20" maxlength="255" value=""> <input type="submit" value="搜索"><input type="hidden" name="domains" value="woodpecker.org.cn/diveintopython"><input type="hidden" name="sitesearch" value="www.woodpecker.org.cn/diveintopython"></p>
               </form>
            </td>
         </tr>
      </table>
      <!--#include virtual="/inc/ads" -->
      <div class="section" lang="zh_cn">
         <div class="titlepage">
            <div>
               <div>
                  <h2 class="title"><a name="re.roman"></a>7.3.&nbsp;个案研究：罗马字母
                  </h2>
               </div>
            </div>
            <div></div>
         </div>
         <div class="toc">
            <ul>
               <li><span class="section"><a href="roman_numerals.html#d0e17763">7.3.1. 校验千位数</a></span></li>
               <li><span class="section"><a href="roman_numerals.html#d0e17955">7.3.2. 校验百位数</a></span></li>
            </ul>
         </div>
         <div class="abstract">
            <p>你可能经常看到罗马数字，即使你没有意识到它们。你可能曾经在老电影或者电视中看到它们 (“<span class="quote">版权所有 <tt class="literal">MCMXLVI</tt></span>” 而不是 “<span class="quote">版权所有<tt class="literal">1946</tt></span>”)，或者在某图书馆或某大学的贡献墙上看到它们 (“<span class="quote">成立于 <tt class="literal">MDCCCLXXXVIII</tt></span>”而不是“<span class="quote">成立于<tt class="literal">1888</tt></span>”)。你也可能在某些文献的大纲或者目录上看到它们。这是一个表示数字的系统，它实际上能够追溯到远古的罗马帝国 (因此而得名)。
            </p>
         </div>
         <p>在罗马数字中，利用7个不同字母进行重复或者组合来表达各式各样的数字。</p>
         <div class="itemizedlist">
            <ul>
               <li><tt class="literal">I</tt> = <tt class="literal">1</tt></li>
               <li><tt class="literal">V</tt> = <tt class="literal">5</tt></li>
               <li><tt class="literal">X</tt> = <tt class="literal">10</tt></li>
               <li><tt class="literal">L</tt> = <tt class="literal">50</tt></li>
               <li><tt class="literal">C</tt> = <tt class="literal">100</tt></li>
               <li><tt class="literal">D</tt> = <tt class="literal">500</tt></li>
               <li><tt class="literal">M</tt> = <tt class="literal">1000</tt></li>
            </ul>
         </div>
         <p>下面是关于构造罗马数字的一些通用的规则的介绍：</p>
         <div class="itemizedlist">
            <ul>
               <li>字符是叠加的。<tt class="literal">I</tt> 表示 <tt class="constant">1</tt>，<tt class="literal">II</tt> 表示 <tt class="literal">2</tt>，而 <tt class="literal">III</tt> 表示 <tt class="literal">3</tt>。<tt class="literal">VI</tt> 表示 <tt class="literal">6</tt> (字面上为逐字符相加，“<span class="quote"><tt class="literal">5</tt> 加 <tt class="literal">1</tt></span>”)，<tt class="literal">VII</tt> 表示 <tt class="literal">7</tt>，<tt class="literal">VIII</tt> 表示 <tt class="literal">8</tt>。
               </li>
               <li>含十字符 (<tt class="literal">I</tt>、<tt class="literal">X</tt>、<tt class="literal">C</tt> 和 <tt class="literal">M</tt>) 至多可以重复三次。对于 <tt class="literal">4</tt>，你则需要利用下一个最大的含五字符进行减操作得到：你不能把 <tt class="literal">4</tt> 表示成 <tt class="literal">IIII</tt>，而应表示为 <tt class="literal">IV</tt> (“<span class="quote">比 <tt class="literal">5</tt> 小 <tt class="literal">1</tt></span>”)。数字 <tt class="literal">40</tt> 写成 <tt class="literal">XL</tt> (比 <tt class="literal">50</tt> 小 <tt class="literal">10</tt>)，<tt class="literal">41</tt> 写成 <tt class="literal">XLI</tt>，<tt class="literal">42</tt> 写成 <tt class="literal">XLII</tt>，<tt class="literal">43</tt> 写成 <tt class="literal">XLIII</tt>，而 <tt class="literal">44</tt> 写成 <tt class="literal">XLIV</tt> (比 <tt class="literal">50</tt> 小 <tt class="literal">10</tt>，然后比 <tt class="literal">5</tt> 小<tt class="literal">1</tt>)。
               </li>
               <li>类似地，对于数字 <tt class="literal">9</tt>，你必须利用下一个含十字符进行减操作得到：<tt class="literal">8</tt> 表示为 <tt class="literal">VIII</tt>，而 <tt class="literal">9</tt> 则表示为 <tt class="literal">IX</tt> (比 <tt class="literal">10</tt> 小 <tt class="literal">1</tt>)，而不是 <tt class="literal">VIIII</tt> (因为字符 <tt class="literal">I</tt> 不能连续重复四次)。数字 <tt class="literal">90</tt> 表示为 <tt class="literal">XC</tt>，<tt class="literal">900</tt> 表示为 <tt class="literal">CM</tt>。
               </li>
               <li>含五字符不能重复。数字 <tt class="literal">10</tt> 常表示为<tt class="literal">X</tt>，而从来不用<tt class="literal">VV</tt>来表示。数字 <tt class="literal">100</tt> 常表示为<tt class="literal">C</tt>，也从来不表示为 <tt class="literal">LL</tt>。
               </li>
               <li>罗马数字一般从高位到低位书写，从左到右阅读，因此不同顺序的字符意义大不相同。<tt class="literal">DC</tt> 表示 <tt class="literal">600</tt>；而 <tt class="literal">CD</tt> 是一个完全不同的数字 (为 <tt class="literal">400</tt>，也就是比 <tt class="literal">500</tt> 小<tt class="literal">100</tt>)。<tt class="literal">CI</tt> 表示 <tt class="literal">101</tt>；而<tt class="literal">IC</tt> 甚至不是一个合法的罗马字母 (因为你不能直接从数字<tt class="literal">100</tt>减去<tt class="literal">1</tt>；这需要写成 <tt class="literal">XCIX</tt>，意思是比 <tt class="literal">100</tt> 小 <tt class="literal">10</tt>，然后加上数字 <tt class="literal">9</tt>，也就是比 <tt class="literal">10</tt> 小 <tt class="literal">1</tt>的数字)。
               </li>
            </ul>
         </div>
         <div class="section" lang="zh_cn">
            <div class="titlepage">
               <div>
                  <div>
                     <h3 class="title"><a name="d0e17763"></a>7.3.1.&nbsp;校验千位数
                     </h3>
                  </div>
               </div>
               <div></div>
            </div>
            <p>怎样校验任意一个字符串是否为一个有效的罗马数字呢？我们每次只看一位数字，由于罗马数字一般是从高位到低位书写。我们从高位开始：千位。对于大于或等于 1000 的数字，千位由一系列的字符 <tt class="literal">M</tt> 表示。
            </p>
            <div class="example"><a name="d0e17771"></a><h3 class="title">例&nbsp;7.3.&nbsp;校验千位数</h3><pre class="screen">
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput"><span class='pykeyword'>import</span> re</span>
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">pattern = <span class='pystring'>'^M?M?M?$'</span></span>       <a name="re.roman.1.1"></a><img src="../images/callouts/1.png" alt="1" border="0" width="12" height="12">
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">re.search(pattern, <span class='pystring'>'M'</span>)</span>    <a name="re.roman.1.2"></a><img src="../images/callouts/2.png" alt="2" border="0" width="12" height="12">
<span class="computeroutput">&lt;SRE_Match object at 0106FB58&gt;</span>
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">re.search(pattern, <span class='pystring'>'MM'</span>)</span>   <a name="re.roman.1.3"></a><img src="../images/callouts/3.png" alt="3" border="0" width="12" height="12">
<span class="computeroutput">&lt;SRE_Match object at 0106C290&gt;</span>
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">re.search(pattern, <span class='pystring'>'MMM'</span>)</span>  <a name="re.roman.1.4"></a><img src="../images/callouts/4.png" alt="4" border="0" width="12" height="12">
<span class="computeroutput">&lt;SRE_Match object at 0106AA38&gt;</span>
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">re.search(pattern, <span class='pystring'>'MMMM'</span>)</span> <a name="re.roman.1.5"></a><img src="../images/callouts/5.png" alt="5" border="0" width="12" height="12">
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">re.search(pattern, <span class='pystring'>''</span>)</span>     <a name="re.roman.1.6"></a><img src="../images/callouts/6.png" alt="6" border="0" width="12" height="12">
<span class="computeroutput">&lt;SRE_Match object at 0106F4A8&gt;</span></pre><div class="calloutlist">
                  <table border="0" summary="Callout list">
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#re.roman.1.1"><img src="../images/callouts/1.png" alt="1" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left">这个模式有三部分：
                           <div class="itemizedlist">
                              <ul>
                                 <li><tt class="literal">^</tt> 表示仅在一个字符串的开始匹配其后的字符串内容。如果没有这个字符，这个模式将匹配出现在字符串任意位置上的
                                    <tt class="literal">M</tt>，而这并不是你想要的。你想确认的是：字符串中是否出现字符 <tt class="literal">M</tt>，如果出现，则必须是在字符串的开始。
                                 </li>
                                 <li><tt class="literal">M?</tt> 可选地匹配单个字符 <tt class="literal">M</tt>，由于它最多可重复出现三次，你可以在一行中匹配 0 次到 3 次字符 <tt class="literal">M</tt>。
                                 </li>
                                 <li><tt class="literal">$</tt> 字符限制模式只能够在一个字符串的结尾匹配。当和模式开头的字符 <tt class="literal">^</tt> 结合使用时，这意味着模式必须匹配整个串，并且在在字符 <tt class="literal">M</tt> 的前后都不能够出现其他的任意字符。
                                 </li>
                              </ul>
                           </div>
                        </td>
                     </tr>
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#re.roman.1.2"><img src="../images/callouts/2.png" alt="2" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left"><tt class="filename">re</tt> 模块的关键是一个 <tt class="function">search</tt> 函数，该函数有两个参数，一个是正则表达式 (<tt class="varname">pattern</tt>)，一个是字符串  (<tt class="literal">'M'</tt>)，函数试图匹配正则表达式。如果发现一个匹配，<tt class="function">search</tt> 函数返回一个拥有多种方法可以描述这个匹配的对象，如果没有发现匹配，<tt class="function">search</tt> 函数返回一个 <tt class="literal">None</tt>，一个 <span class="application">Python</span> 空值 (null value)。你此刻关注的唯一事情，就是模式是否匹配上，于是我们利用 <tt class="function">search</tt> 函数的返回值了解这个事实。字符串<tt class="literal">'M'</tt> 匹配上这个正则表达式，因为第一个可选的 <tt class="literal">M</tt> 匹配上，而第二个和第三个 <tt class="literal">M</tt> 被忽略掉了。
                        </td>
                     </tr>
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#re.roman.1.3"><img src="../images/callouts/3.png" alt="3" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left"><tt class="literal">'MM'</tt> 能匹配上是因为第一和第二个可选的 <tt class="literal">M</tt> 匹配上，而忽略掉第三个 <tt class="literal">M</tt>。
                        </td>
                     </tr>
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#re.roman.1.4"><img src="../images/callouts/4.png" alt="4" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left"><tt class="literal">'MMM'</tt> 能匹配上因为三个 <tt class="literal">M</tt> 都匹配上了。
                        </td>
                     </tr>
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#re.roman.1.5"><img src="../images/callouts/5.png" alt="5" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left"><tt class="literal">'MMMM'</tt> 没有匹配上。因为所有的三个 <tt class="literal">M</tt> 都匹配完了，但是正则表达式还有字符串尾部的限制 (由于字符 <tt class="literal">$</tt>)，而字符串又没有结束 (因为还有第四个 <tt class="literal">M</tt> 字符)，因此 <tt class="function">search</tt> 函数返回一个 <tt class="literal">None</tt>。
                        </td>
                     </tr>
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#re.roman.1.6"><img src="../images/callouts/6.png" alt="6" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left">有趣的是，一个空字符串也能够匹配这个正则表达式，因为所有的字符 <tt class="literal">M</tt> 都是可选的。
                        </td>
                     </tr>
                  </table>
               </div>
            </div>
         </div>
         <div class="section" lang="zh_cn">
            <div class="titlepage">
               <div>
                  <div>
                     <h3 class="title"><a name="d0e17955"></a>7.3.2.&nbsp;校验百位数
                     </h3>
                  </div>
               </div>
               <div></div>
            </div>
            <p>与千位数相比，百位数识别起来要困难得多，这是因为有多种相互独立的表达方式都可以表达百位数，而具体用那种方式表达和具体的数值有关。</p>
            <div class="itemizedlist">
               <ul>
                  <li><tt class="literal">100</tt> = <tt class="literal">C</tt></li>
                  <li><tt class="literal">200</tt> = <tt class="literal">CC</tt></li>
                  <li><tt class="literal">300</tt> = <tt class="literal">CCC</tt></li>
                  <li><tt class="literal">400</tt> = <tt class="literal">CD</tt></li>
                  <li><tt class="literal">500</tt> = <tt class="literal">D</tt></li>
                  <li><tt class="literal">600</tt> = <tt class="literal">DC</tt></li>
                  <li><tt class="literal">700</tt> = <tt class="literal">DCC</tt></li>
                  <li><tt class="literal">800</tt> = <tt class="literal">DCCC</tt></li>
                  <li><tt class="literal">900</tt> = <tt class="literal">CM</tt></li>
               </ul>
            </div>
            <p>因此有四种可能的模式：</p>
            <div class="itemizedlist">
               <ul>
                  <li><tt class="literal">CM</tt></li>
                  <li><tt class="literal">CD</tt></li>
                  <li>零到三次出现 <tt class="literal">C</tt> 字符 (出现零次表示百位数为 0)
                  </li>
                  <li><tt class="literal">D</tt>，后面跟零个到三个 <tt class="literal">C</tt> 字符
                  </li>
               </ul>
            </div>
            <p>后面两个模式可以结合到一起：</p>
            <div class="itemizedlist">
               <ul>
                  <li>一个可选的字符 <tt class="literal">D</tt>，加上零到 3 个 <tt class="literal">C</tt> 字符。
                  </li>
               </ul>
            </div>
            <p>这个例子显示如何有效地识别罗马数字的百位数。</p>
            <div class="example"><a name="re.roman.hundreds"></a><h3 class="title">例&nbsp;7.4.&nbsp;检验百位数</h3><pre class="screen">
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput"><span class='pykeyword'>import</span> re</span>
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">pattern = <span class='pystring'>'^M?M?M?(CM|CD|D?C?C?C?)$'</span></span> <a name="re.roman.2.1"></a><img src="../images/callouts/1.png" alt="1" border="0" width="12" height="12">
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">re.search(pattern, <span class='pystring'>'MCM'</span>)</span>            <a name="re.roman.2.2"></a><img src="../images/callouts/2.png" alt="2" border="0" width="12" height="12">
<span class="computeroutput">&lt;SRE_Match object at 01070390&gt;</span>
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">re.search(pattern, <span class='pystring'>'MD'</span>)</span>             <a name="re.roman.2.3"></a><img src="../images/callouts/3.png" alt="3" border="0" width="12" height="12">
<span class="computeroutput">&lt;SRE_Match object at 01073A50&gt;</span>
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">re.search(pattern, <span class='pystring'>'MMMCCC'</span>)</span>         <a name="re.roman.2.4"></a><img src="../images/callouts/4.png" alt="4" border="0" width="12" height="12">
<span class="computeroutput">&lt;SRE_Match object at 010748A8&gt;</span>
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">re.search(pattern, <span class='pystring'>'MCMC'</span>)</span>           <a name="re.roman.2.5"></a><img src="../images/callouts/5.png" alt="5" border="0" width="12" height="12">
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">re.search(pattern, <span class='pystring'>''</span>)</span>               <a name="re.roman.2.6"></a><img src="../images/callouts/6.png" alt="6" border="0" width="12" height="12">
<span class="computeroutput">&lt;SRE_Match object at 01071D98&gt;</span></pre><div class="calloutlist">
                  <table border="0" summary="Callout list">
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#re.roman.2.1"><img src="../images/callouts/1.png" alt="1" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left">这个模式的首部和上一个模式相同，检查字符串的开始 (<tt class="literal">^</tt>)，接着匹配千位数 (<tt class="literal">M?M?M?</tt>)，然后才是这个模式的新内容。在括号内，定义了包含有三个互相独立的模式集合，由垂直线隔开：<tt class="literal">CM</tt>、<tt class="literal">CD</tt> 和 <tt class="literal">D?C?C?C?</tt> (<tt class="literal">D</tt>是可选字符，接着是 0 到 3 个可选的 <tt class="literal">C</tt> 字符)。正则表达式解析器依次检查这些模式 (从左到右)，如果匹配上第一个模式，则忽略剩下的模式。
                        </td>
                     </tr>
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#re.roman.2.2"><img src="../images/callouts/2.png" alt="2" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left"><tt class="literal">'MCM'</tt> 匹配上，因为第一个 <tt class="literal">M</tt> 字符匹配，第二和第三个 <tt class="literal">M</tt> 字符被忽略掉，而 <tt class="literal">CM</tt> 匹配上 (因此 <tt class="literal">CD</tt> 和 <tt class="literal">D?C?C?C?</tt> 两个模式不再考虑)。<tt class="literal">MCM</tt> 表示罗马数字<tt class="literal">1900</tt>。
                        </td>
                     </tr>
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#re.roman.2.3"><img src="../images/callouts/3.png" alt="3" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left"><tt class="literal">'MD'</tt> 匹配上，因为第一个字符 <tt class="literal">M</tt> 匹配上，第二第三个 <tt class="literal">M</tt> 字符忽略，而模式 <tt class="literal">D?C?C?C?</tt> 匹配上 <tt class="literal">D</tt> (模式中的三个可选的字符 <tt class="literal">C</tt> 都被忽略掉了)。<tt class="literal">MD</tt> 表示罗马数字 <tt class="literal">1500</tt>。
                        </td>
                     </tr>
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#re.roman.2.4"><img src="../images/callouts/4.png" alt="4" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left"><tt class="literal">'MMMCCC'</tt> 匹配上，因为三个 <tt class="literal">M</tt> 字符都匹配上，而模式 <tt class="literal">D?C?C?C?</tt> 匹配上 <tt class="literal">CCC</tt> (字符<tt class="literal">D</tt>是可选的，此处忽略)。<tt class="literal">MMMCCC</tt> 表示罗马数字 <tt class="literal">3300</tt>。
                        </td>
                     </tr>
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#re.roman.2.5"><img src="../images/callouts/5.png" alt="5" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left"><tt class="literal">'MCMC'</tt> 没有匹配上。第一个 <tt class="literal">M</tt> 字符匹配上，第二第三个 <tt class="literal">M</tt> 字符忽略，接着是 <tt class="literal">CM</tt> 匹配上，但是接着是 <tt class="literal">$</tt> 字符没有匹配，因为字符串还没有结束 (你仍然还有一个没有匹配的<tt class="literal">C</tt>字符)。<tt class="literal">C</tt> 字符也<span class="emphasis"><em>不</em></span> 匹配模式 <tt class="literal">D?C?C?C?</tt> 的一部分，因为与之相互独立的模式 <tt class="literal">CM</tt> 已经匹配上。
                        </td>
                     </tr>
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#re.roman.2.6"><img src="../images/callouts/6.png" alt="6" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left">有趣的是，一个空字符串也可以匹配这个模式，因为所有的 <tt class="literal">M</tt> 字符都是可选的，它们都被忽略，并且一个空字符串可以匹配 <tt class="literal">D?C?C?C?</tt> 模式，此处所有的字符也都是可选的，并且都被忽略。
                        </td>
                     </tr>
                  </table>
               </div>
            </div>
            <p>哎呀！看看正则表达式能够多快变得难以理解？你仅仅表示了罗马数字的千位和百位上的数字。如果你根据类似的方法，十位数和各位数就非常简单了，因为是完全相同的模式。让我们来看表达这个模式的另一种方式吧。</p>
         </div>
      </div>
      <table class="Footer" width="100%" border="0" cellpadding="0" cellspacing="0" summary="">
         <tr>
            <td width="35%" align="left"><br><a class="NavigationArrow" href="street_addresses.html">&lt;&lt;&nbsp;个案研究：街道地址</a></td>
            <td width="30%" align="center"><br>&nbsp;<span class="divider">|</span>&nbsp;<a href="index.html#re.intro" title="7.1.&nbsp;概览">1</a> <span class="divider">|</span> <a href="street_addresses.html" title="7.2.&nbsp;个案研究：街道地址">2</a> <span class="divider">|</span> <span class="thispage">3</span> <span class="divider">|</span> <a href="n_m_syntax.html" title="7.4.&nbsp;使用 {n,m} 语法">4</a> <span class="divider">|</span> <a href="verbose.html" title="7.5.&nbsp;松散正则表达式">5</a> <span class="divider">|</span> <a href="phone_numbers.html" title="7.6.&nbsp;个案研究：解析电话号码">6</a> <span class="divider">|</span> <a href="summary.html" title="7.7.&nbsp;小结">7</a>&nbsp;<span class="divider">|</span>&nbsp;
            </td>
            <td width="35%" align="right"><br><a class="NavigationArrow" href="n_m_syntax.html">使用 {n,m} 语法&nbsp;&gt;&gt;</a></td>
         </tr>
         <tr>
            <td colspan="3"><br></td>
         </tr>
      </table>
      <div class="Footer">
         <p class="copyright">Copyright © 2000, 2001, 2002, 2003, 2004 <a href="mailto:mark@diveintopython.org">Mark Pilgrim</a></p>
         <p class="copyright">Copyright © 2001, 2002, 2003, 2004, 2005, 2006, 2007 <a href="mailto:python-cn@googlegroups.com">CPyUG (邮件列表)</a></p>
      </div>
   </body>
</html>